package cn.ygh.bbo.generator.service;

import cn.ygh.bbo.generator.config.Config;
import cn.ygh.bbo.generator.entity.Clazz;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import static freemarker.template.Configuration.VERSION_2_3_22;

/**
 * @author ygh
 * @Type FreemarkerUtils.java
 * @Desc
 * @date 2019/10/9
 * @Version V2.0
 */
public class FreemarkerService {

    public static FreemarkerService getInstance() throws IOException, TemplateException {
        Configuration cfg=new Configuration(VERSION_2_3_22);
        Config config=Config.getInstance();
        cfg.setClassForTemplateLoading(FreemarkerService.class,"/templates");
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        //通用属性
        cfg.setSharedVariable("packageName",config.getPackageName());
        cfg.setSharedVariable("projectName",config.getProjectName());
        //模板相关配置
        Properties properties=new Properties();
        properties.load(FreemarkerService.class.getClassLoader().getResourceAsStream("freemarker.properties"));
        cfg.setSettings(properties);
        FreemarkerService freemarkerUtil=new FreemarkerService();
        freemarkerUtil.init(cfg);
        return freemarkerUtil;
    }
    /**
     * 通用bean的模板 基础实体类 用于查询 传参
     */
    private Template beanTmp;
    //通用dao的模板
    private Template mapperTmp;
    //xml
    private Template mapperXmlTmp;
    //通用service的模板
    private Template serviceTmp;
    //通用serviceImpl的模板
    private Template serviceImplTmp;
    //管理员api的模板
    private Template restpageControllerTmp;
    //index页面
    private Template indexTmp;
    //update页面
    private Template updateTmp;
    //create页面
    private Template createTmp;
    //show页面
    private Template showTmp;
    //sql
    private Template sqlTmp;
    //配置
    private Config config=Config.getInstance();
    /**
     * 初始化工具
     * @param cfg
     */
    private void init(Configuration cfg) throws IOException {
        beanTmp=cfg.getTemplate("java/bean.ftl");
        mapperTmp=cfg.getTemplate("java/mapper.ftl");
        mapperXmlTmp=cfg.getTemplate("xml/mapperXml.ftl");
        serviceTmp=cfg.getTemplate("java/service.ftl");
        serviceImplTmp=cfg.getTemplate("java/serviceImpl.ftl");
        restpageControllerTmp=cfg.getTemplate("java/restpageController.ftl");
        indexTmp=cfg.getTemplate("html/index.ftl");
        updateTmp=cfg.getTemplate("html/update.ftl");
        createTmp=cfg.getTemplate("html/create.ftl");
        showTmp=cfg.getTemplate("html/show.ftl");
        sqlTmp=cfg.getTemplate("sql/sql.ftl");
    }

    /**
     * 生成代码
     */
    public void generate(Clazz clazz){
        try {
            generateBean(clazz);
            generateMapper(clazz);
            generateMapperXml(clazz);
            generateService(clazz);
            generateServiceImpl(clazz);
            generateRestPageController(clazz);
            generateIndex(clazz);
            generateShow(clazz);
            generateCreate(clazz);
            generateUpdate(clazz);
            generateSql(clazz);
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
    }
    /**
     * 生成bean 文件
     * @param clazz
     */
    private void generateBean(Clazz clazz) throws IOException, TemplateException {
        String save=config.getProjectName()+"/java/"+config.getPackageName().replaceAll("\\.","/")
                +"/bean/"+clazz.getName()+".java";
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("clazz",clazz);
        fileGenerate(beanTmp, map, save);
    }

    /**
     * 生成mapper
     * @param clazz
     * @throws IOException
     * @throws TemplateException
     */
    private void generateMapper(Clazz clazz) throws IOException, TemplateException {
        String save=config.getProjectName()+"/java/"+config.getPackageName().replaceAll("\\.","/")
                +"/mapper/"+clazz.getName()+"Mapper.java";
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("clazz",clazz);
        fileGenerate(mapperTmp, map, save);
    }

    /**
     * 生成xml
     * @param clazz
     * @throws IOException
     * @throws TemplateException
     */
    private void generateMapperXml(Clazz clazz) throws IOException, TemplateException {
        String save=config.getProjectName()+"/resources/mapper/"+clazz.getName()+"Mapper.xml";
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("clazz",clazz);
        fileGenerate(mapperXmlTmp, map, save);
    }

    /**
     * 生成service
     * @param clazz
     * @throws IOException
     * @throws TemplateException
     */
    private void generateService(Clazz clazz) throws IOException, TemplateException {
        String save=config.getProjectName()+"/java/"+config.getPackageName().replaceAll("\\.","/")
                +"/service/"+clazz.getName()+"Service.java";
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("clazz",clazz);
        fileGenerate(serviceTmp, map, save);
    }

    /**
     * 生成service
     * @param clazz
     * @throws IOException
     * @throws TemplateException
     */
    private void generateServiceImpl(Clazz clazz) throws IOException, TemplateException {
        String save=config.getProjectName()+"/java/"+config.getPackageName().replaceAll("\\.","/")
                +"/service/impl/"+clazz.getName()+"ServiceImpl.java";
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("clazz",clazz);
        fileGenerate(serviceImplTmp, map, save);
    }

    /**
     * 生成RestPageController
     * @param clazz
     * @throws IOException
     * @throws TemplateException
     */
    private void generateRestPageController(Clazz clazz) throws IOException, TemplateException {
        String save=config.getProjectName()+"/java/"+config.getPackageName().replaceAll("\\.","/")
                +"/web/controller/"+clazz.getName()+"Controller.java";
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("clazz",clazz);
        fileGenerate(restpageControllerTmp, map, save);
    }


    /**
     * 生成edit
     * @param clazz
     * @throws IOException
     * @throws TemplateException
     */
    private void generateUpdate(Clazz clazz) throws IOException, TemplateException {
        String save=config.getProjectName()+"/resources/page/"+clazz.getName()+"/Update.vue";
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("clazz",clazz);
        fileGenerate(updateTmp, map, save);
    }

    /**
     * 生成show
     * @param clazz
     * @throws IOException
     * @throws TemplateException
     */
    private void generateShow(Clazz clazz) throws IOException, TemplateException {
        String save=config.getProjectName()+"/resources/page/"+clazz.getName()+"/Show.vue";
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("clazz",clazz);
        fileGenerate(showTmp, map, save);
    }

    /**
     * 生成add
     * @param clazz
     * @throws IOException
     * @throws TemplateException
     */
    private void generateCreate(Clazz clazz) throws IOException, TemplateException {
        String save=config.getProjectName()+"/resources/page/"+clazz.getName()+"/Create.vue";
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("clazz",clazz);
        fileGenerate(createTmp, map, save);
    }

    /**
     * 生成index
     * @param clazz
     * @throws IOException
     * @throws TemplateException
     */
    private void generateIndex(Clazz clazz) throws IOException, TemplateException {
        String save=config.getProjectName()+"/resources/page/"+clazz.getName()+"/Index.vue";
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("clazz",clazz);
        fileGenerate(indexTmp, map, save);
    }
    /**
     * 生成sql
     * @param clazz
     * @throws IOException
     * @throws TemplateException
     */
    private void generateSql(Clazz clazz) throws IOException, TemplateException {
        String save=config.getProjectName()+"/resources/sql/"+clazz.getName()+".sql";
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("clazz",clazz);
        fileGenerate(sqlTmp, map, save);
    }



    private void fileGenerate(Template template,Map<String,Object>map,String save) throws IOException, TemplateException {
        save="bbo-generator/"+save;
        File file=new File(save);
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        template.process(map,new FileWriter(file));
    }


}
